#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using Alone.Handlers;
using Alone.GameObjects;

using AloneLibrary.Services.Camera;
using AloneLibrary.Services.Input;

#endregion

namespace Alone
{
	/// <summary>
	/// This screen implements the actual game logic. It is just a
	/// placeholder to get the idea across: you'll probably want to
	/// put some more interesting gameplay in here!
	/// </summary>
	class GameplayScreen : GameScreen
	{
		#region Fields

		NetworkSession networkSession;

		ContentManager content;
		SpriteFont gameFont;

		Vector2 playerPosition = new Vector2(100, 100);
		Vector2 enemyPosition = new Vector2(100, 100);

		Random random = new Random();
		Matrix world = Matrix.Identity;

		BasicEffect effect;
		ICameraHandler camera;
		EnvironmentHandler envHandler;
		PlayerHandler playerHandler;
        IInputHandler input;
        EnemyHandler enemyHandler;
	
		#endregion

		#region Properties


		/// <summary>
		/// The logic for deciding whether the game is paused depends on whether
		/// this is a networked or single player game. If we are in a network session,
		/// we should go on updating the game even when the user tabs away from us or
		/// brings up the pause menu, because even though the local player is not
		/// responding to input, other remote players may not be paused. In single
		/// player modes, however, we want everything to pause if the game loses focus.
		/// </summary>
		new bool IsActive
		{
			get
			{
				if (networkSession == null)
				{
					// Pause behavior for single player games.
					return base.IsActive;
				}
				else
				{
					// Pause behavior for networked games.
					return !IsExiting;
				}
			}
		}


		#endregion

		#region Initialization


		/// <summary>
		/// Constructor.
		/// </summary>
		public GameplayScreen(NetworkSession networkSession)
		{
			this.networkSession = networkSession;

			TransitionOnTime = TimeSpan.FromSeconds(1.5);
			TransitionOffTime = TimeSpan.FromSeconds(0.5);
		}

		/// <summary>
		/// Load graphics content for the game.
		/// </summary>
		public override void LoadContent()
		{
			if (content == null)
				content = new ContentManager(ScreenManager.Game.Services, "Content");

			gameFont = content.Load<SpriteFont>("gamefont");

			effect = new BasicEffect(ScreenManager.GraphicsDevice, null);

			this.camera = (ICameraHandler)ScreenManager.Game.Services.GetService(typeof(ICameraHandler));
            this.input = (IInputHandler)ScreenManager.Game.Services.GetService(typeof(IInputHandler));

			this.envHandler = new EnvironmentHandler(ScreenManager.Game);
			this.playerHandler = new PlayerHandler(ScreenManager.Game, networkSession, ScreenManager);
            this.enemyHandler = new EnemyHandler(ScreenManager.Game, playerHandler);

			ScreenManager.Game.Components.Add(envHandler);
			ScreenManager.Game.Components.Add(playerHandler);
            ScreenManager.Game.Components.Add(enemyHandler);

			// A real game would probably have more content than this sample, so
			// it would take longer to load. We simulate that by delaying for a
			// while, giving you a chance to admire the beautiful loading screen.
			Thread.Sleep(1000);

			// once the load has finished, we use ResetElapsedTime to tell the game's
			// timing mechanism that we have just finished a very long frame, and that
			// it should not try to catch up.
			ScreenManager.Game.ResetElapsedTime();
		}


		/// <summary>
		/// Unload graphics content used by the game.
		/// </summary>
		public override void UnloadContent()
		{
			ScreenManager.Game.Components.Remove(envHandler);
			ScreenManager.Game.Components.Remove(playerHandler);
            ScreenManager.Game.Components.Remove(enemyHandler);
			
			content.Unload();
		}
		#endregion

		#region Update and Draw
		/// <summary>
		/// Updates the state of the game.
		/// </summary>
		public override void Update(GameTime gameTime, bool otherScreenHasFocus,
													   bool coveredByOtherScreen)
		{
			base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);


            if (IsActive)
            {
                this.setGraphicsDevice();

                playerHandler.Enabled = true;
                enemyHandler.Enabled = true;
                envHandler.Enabled = true;
            }
            else
            {
                playerHandler.Enabled = false;
                enemyHandler.Enabled = false;
                envHandler.Enabled = false;
            }

			// If we are in a network game, check if we should return to the lobby.
			if ((networkSession != null) && !IsExiting)
			{
				if (networkSession.SessionState == NetworkSessionState.Lobby)
				{
					LoadingScreen.Load(ScreenManager, true, null,
									   new BackgroundScreen(),
									   new LobbyScreen(networkSession));
				}
			}
		}

		// Taken from http://blogs.msdn.com/shawnhar/archive/2006/11/13/spritebatch-and-renderstates.aspx
		// due to 3D and 2D rendering problems
		private void setGraphicsDevice()
		{
			ScreenManager.Game.GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace;
			ScreenManager.Game.GraphicsDevice.RenderState.DepthBufferEnable = false;

			ScreenManager.Game.GraphicsDevice.RenderState.AlphaBlendEnable = true;
			ScreenManager.Game.GraphicsDevice.RenderState.AlphaBlendOperation = BlendFunction.Add;
			ScreenManager.Game.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
			ScreenManager.Game.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
			ScreenManager.Game.GraphicsDevice.RenderState.SeparateAlphaBlendEnabled = false;

			ScreenManager.Game.GraphicsDevice.RenderState.AlphaTestEnable = true;
			ScreenManager.Game.GraphicsDevice.RenderState.AlphaFunction = CompareFunction.Greater;
			ScreenManager.Game.GraphicsDevice.RenderState.ReferenceAlpha = 0;

			ScreenManager.Game.GraphicsDevice.SamplerStates[0].AddressU = TextureAddressMode.Clamp;
			ScreenManager.Game.GraphicsDevice.SamplerStates[0].AddressV = TextureAddressMode.Clamp;

			ScreenManager.Game.GraphicsDevice.SamplerStates[0].MagFilter = TextureFilter.Linear;
			ScreenManager.Game.GraphicsDevice.SamplerStates[0].MinFilter = TextureFilter.Linear;
			ScreenManager.Game.GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.Linear;

			ScreenManager.Game.GraphicsDevice.SamplerStates[0].MipMapLevelOfDetailBias = 0.0f;
			ScreenManager.Game.GraphicsDevice.SamplerStates[0].MaxMipLevel = 0;

			ScreenManager.Game.GraphicsDevice.RenderState.DepthBufferEnable = true;
			ScreenManager.Game.GraphicsDevice.RenderState.AlphaBlendEnable = false;
			ScreenManager.Game.GraphicsDevice.RenderState.AlphaTestEnable = false;

			ScreenManager.Game.GraphicsDevice.SamplerStates[0].AddressU = TextureAddressMode.Wrap;
			ScreenManager.Game.GraphicsDevice.SamplerStates[0].AddressV = TextureAddressMode.Wrap;

		}


		/// <summary>
		/// Draws the gameplay screen.
		/// </summary>
		public override void Draw(GameTime gameTime)
		{
			// This game has a blue background. Why? Because!
			ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
											   Color.CornflowerBlue, 0, 0);

            playerHandler.Draw(gameTime);

            //if (networkSession != null)
            //{
            //    string message = "Players: " + networkSession.AllGamers.Count;
            //    Vector2 messagePosition = new Vector2(100, 480);
            //    // spriteBatch.DrawString(gameFont, message, messagePosition, Color.White);
            //}

	
			// If the game is transitioning on or off, fade it out to black.
			if (TransitionPosition > 0)
				ScreenManager.FadeBackBufferToBlack(255 - TransitionAlpha);

			base.Draw(gameTime);
		}


		#endregion
	}
}
